package com.luckdraw.service.impl;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;

import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.http.Header;
import org.nutz.http.Http;
import org.nutz.http.Response;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;

import com.luckdraw.domain.Activity;
import com.luckdraw.domain.ActivityLog;
import com.luckdraw.domain.Codes;
import com.luckdraw.domain.CommissionLog;
import com.luckdraw.domain.Order;
import com.luckdraw.domain.User;
import com.luckdraw.domain.WithdrawalLog;
import com.luckdraw.service.GameService;
import com.luckdraw.service.ActivityService;
import com.luckdraw.service.TenpayService;
import com.luckdraw.util.ClientSendHongBaoCustomSSL;

@IocBean(name="activityService")
public class ActivityImpl implements ActivityService{
	
	private static Log log = Logs.getLog("ActivityService");
	
	@Inject
	private Dao dao;
	
	@Inject
	private GameService gameService;
	
	@Inject
	private TenpayService tenpayService;
	
	@Inject("java:$conf.get('tenpay.appId')")
	private String appId;
	
	@Inject("java:$conf.get('weixin.api.secret')")
	private String weixinSecret;
	
	@Inject("java:$conf.get('weixin.api.tokenUrl')")
	private String tokenUrl;
	
	@Inject("java:$conf.get('weixin.api.userInfo')")
	private String userInfoUrl;
	
	@Inject("java:$conf.get('tenpay.apiKey')")
	private String apiKey;
	
	@Inject CacheManager cacheManager;
	
	
	/**
	 * 获取已上线的活动列表
	 * @return
	 */
	public List<Activity> getLuckDrawSetList(){
		return dao.query(Activity.class, Cnd.where("status", "=", 1).orderBy("cost","asc"));
	}
	
	/**
	 * 查询set信息
	 * @param setId
	 * @return
	 */
	public Activity getLuckDrawSet(int setId){
		return dao.fetch(Activity.class, setId);
	}
	
	/**
	 * 用户注册
	 * @param weixinOpenId	微信openId
	 * @param recommendUserId	推荐人用户ID
	 */
	public boolean register(String weixinOpenId,String recommendUserId) {
		String access_token = "";
		Cache cache = cacheManager.getCache("tockCache");
		Element e = cache.get("ACCESS_TOKEN");
		if(null != e && null != e.getValue()){
			access_token=(String) e.getValue();
		}
		synchronized (this) {
			User user = dao.fetch(User.class, Cnd.where("userId", "=", weixinOpenId));
			if(user==null){
				String nickname = "";
				if(!Strings.isNotBlank(access_token)){
					Response response = Http.get(tokenUrl.replaceFirst("P_APPID", appId).replaceFirst("P_SECRET", weixinSecret));
					if(response.isOK()){
						access_token = NutMap.WRAP(response.getContent()).getString("access_token");
						cache.put(new Element("ACCESS_TOKEN",access_token));
					}
				}
				Response response = Http.get(userInfoUrl.replaceFirst("P_ACCESS_TOKEN", access_token).replaceFirst("P_OPENID", weixinOpenId), Header.create().set("Accept-Charset", "GBK"), 60000);
				if(response.isOK()){
					NutMap respMap = NutMap.WRAP(response.getContent());
					if(respMap.containsKey("subscribe")&&respMap.getInt("subscribe")==1){
						nickname = NutMap.WRAP(response.getContent()).getString("nickname");
					}
				}
				user = new User();
				user.setUserId(weixinOpenId);
				user.setNickName2(nickname);
				user.setWxAppId(appId);
				user.setAmount(0);
				user.setRegisterTime(new Date());
				//只有推荐人与注册人不一致时才设置推荐人
				if(!weixinOpenId.equals(recommendUserId)){
					user.setAgentUserId(recommendUserId);
				}
				dao.insert(user);
				return true;
			}else{
				return true;
			}
		}
	}
	
	public void pay(String weixinOpenId,int setId){
		
	}
	
	/**
	 * 获取用户信息
	 * @param weixinOpenId
	 * @return
	 */
	public User getUser(String weixinOpenId){
		return dao.fetch(User.class, Cnd.where("userId", "=", weixinOpenId));
	}
	
	/**
	 * 查询参与记录
	 * @param weixinOpenId
	 * @return
	 */
	public List<ActivityLog> getLuckDrawLogList(String weixinOpenId) {
		return dao.query(ActivityLog.class, Cnd.where("userId", "=", weixinOpenId).orderBy("partakeTime", "desc"));
	}
	
	/**
	 * 查询佣金获取记录
	 * @param weixinOpenId
	 * @return
	 */
	public List<CommissionLog> getCommissionLogs(String weixinOpenId) {
		return dao.query(CommissionLog.class, Cnd.where("userId", "=", weixinOpenId).orderBy("payTime", "desc"));
	}
	
	/**
	 * 提现
	 * @param weixinOpenId
	 */
	public boolean withdrawals(String weixinOpenId, String mch_id, String wxappid) {
		synchronized (this) {
			User user = dao.fetch(User.class, Cnd.where("userId", "=", weixinOpenId).and("amount", ">=", 100));
			if (user != null) {
				if (minusUserAmount(weixinOpenId, user.getAmount())) {
					String err_code = "";
					try {
						log.info("withdrawals|openid:" + weixinOpenId + ",扣款成功扣款金额:" + user.getAmount());
						WithdrawalLog lo = tenpayService.withdrawals(weixinOpenId, user.getAmount());
						err_code = lo.getErrCode();
						dao.insert(lo);
						if("0".equals(lo.getState())){
							log.info("withdrawals|openid:" + weixinOpenId + ",微信提现成功提现金额:" + user.getAmount()+",err_code:" + err_code);
							return true;
						}
					} catch (Exception e) {
						log.info("withdrawals|openid:" + weixinOpenId + ",微信提现失败异常:" + user.getAmount()+",err_code:" + err_code);
					}
					log.info("withdrawals|openid:" + weixinOpenId + ",微信提现失败资金回滚回滚金额:" + user.getAmount()+",err_code:" + err_code);
					// 发包失败回滚金额
					addUserAmount(weixinOpenId, user.getAmount());
					return false;
				}
				return false;
			}
		}
		return false;
	}
	
	/**
	 * 创建红包订单
	 * @param weixinOpenId
	 * @param setId
	 * @return
	 */
	public String createOrder(String weixinOpenId,int actId){
		User user = dao.fetch(User.class, Cnd.where("userId", "=", weixinOpenId));
		if(user!=null){
			Activity set = dao.fetch(Activity.class, actId);
			Order order = new Order();
			order.setUserId(weixinOpenId);
			order.setOrderId(UUID.randomUUID().toString().replaceAll("-", ""));
			order.setActivityId(actId);
			order.setAmount(set.getCost());
			order.setStatus(0);
			order.setPayTime(new Date());
			String goodsBody = "欢喜过福年，拼手气分2亿";
			Codes code = dao.fetch(Codes.class, Cnd.where("key", "=", "goods_body"));
			if(code!=null){
				goodsBody = code.getValue();
			}
			//余额足够时使用余额支付
			if(user.getAmount()>=set.getCost()){
				if(minusUserAmount(weixinOpenId,set.getCost())){
					order.setPayType(Order.PAY_TYPE_BALANCE);
					order.setPrepayId(order.getOrderId());
					dao.insert(order);
					finishedOrder(order.getOrderId(), order.getUserId(), order.getOrderId());
					return "BALANCE";
				}
			}
			String localIp;
			try {
				localIp = InetAddress.getLocalHost().getHostAddress();
			} catch (UnknownHostException e) {
				localIp = "121.199.14.69";
			}
			String prepayId = tenpayService.unifiedOrder(goodsBody, goodsBody, order.getOrderId(), order.getAmount()+"", localIp, weixinOpenId);
			if(!Strings.isEmpty(prepayId)){
				order.setPayType(Order.PAY_TYPE_WX);
				order.setPrepayId(prepayId);
				dao.insert(order);
				return prepayId;
			}
		}
		return "";
	}
	
	/**
	 * 完成支付订单
	 * @param orderId
	 * @param openId
	 * @param transactionId
	 */
	public void finishedOrder(String orderId,String openId,String transactionId){
		//更新订单状态
		int count = dao.update(Order.class, Chain.make("status", 1).add("transactionId", transactionId), Cnd.where("orderId", "=", orderId).and("userId", "=", openId).and("status", "=", 0));
		if(count>0){//若订单更新正常则执行抽奖
			log.info("finishedOrder|openId:"+openId+",orderId:"+orderId+",transactionId:"+transactionId+"|订单状态更新成功");
			Order order = dao.fetch(Order.class, Cnd.where("orderId", "=", orderId));
			if(order!=null&&order.getStatus().intValue()==1){//订单状态为完成时执行抽奖操作
				int reward = gameService.getReward(order.getActivityId());
				if(reward==0){
					Codes codes;
					//默认分成比例为10%
					int commission_rate = 10;
					if((codes=dao.fetch(Codes.class, Cnd.where("key", "=", "commission_rate")))!=null){//从配置信息中获取分成比例
						commission_rate = Integer.parseInt(codes.getValue());
					}
					reward = order.getAmount()-(order.getAmount()/commission_rate);
				}
				addUserAmount(order.getUserId(),reward);
				ActivityLog actLog = new ActivityLog();
				actLog.setOrderId(order.getOrderId());
				actLog.setPayAmount(order.getAmount());
				actLog.setUserId(order.getUserId());
				actLog.setPartakeTime(new Date());
				actLog.setGainAmount(reward);
				actLog.setPayType(order.getPayType());
				dao.insert(actLog);
				//只有微信支付时才参与分成
				if(!Order.PAY_TYPE_BALANCE.equals(order.getPayType())){
					User user;
					if((user=dao.fetch(User.class, Cnd.where("userId", "=", openId)))!=null){
						if(Strings.isNotBlank(user.getAgentUserId())){//判断是否有推广人
							User agentUser;
							if((agentUser = dao.fetch(User.class, Cnd.where("userId", "=", user.getAgentUserId())))!=null){//获取推广人信息
								Codes codes;
								//默认分成比例为10%
								int commission_rate = 10;
								if((codes=dao.fetch(Codes.class, Cnd.where("key", "=", "commission_rate")))!=null){//从配置信息中获取分成比例
									commission_rate = Integer.parseInt(codes.getValue());
								}
								//计算分成金额
								int commission = order.getAmount()/commission_rate;
								CommissionLog coml = new CommissionLog();
								coml.setUserId(agentUser.getUserId());
								coml.setOrderId(order.getOrderId());
								coml.setPayAmount(order.getAmount());
								coml.setPayTime(actLog.getPartakeTime());
								coml.setCommission(commission);
								coml.setSubUserId(user.getUserId());
								coml.setSubNickName(user.getNickName());
								//发放分成金额
								addUserAmount(agentUser.getUserId(), commission);
								//写入分成日志
								dao.insert(coml);
								log.info("agentCommission|openId:"+openId+",orderId:"+orderId+",transactionId:"+transactionId+",agentUserId:"+coml.getUserId()+",commission:"+commission);
							}
						}
					}
				}
				log.info("finishedOrder|openId:"+openId+",orderId:"+orderId+",transactionId:"+transactionId+"|抽奖日志生成成功");
			}
		}else{
			log.info("finishedOrder|openId:"+openId+",orderId:"+orderId+",transactionId:"+transactionId+"|订单状态更新失败");
		}
	}
	
	/**
	 * 添加账号余额
	 * @param userId
	 * @param amount
	 * @return
	 */
	public boolean addUserAmount(String userId,int amount){
		return updateUserAmount(userId, amount, "+");
	}
	
	/**
	 * 减少账号余额
	 * @param userId
	 * @param amount
	 * @return
	 */
	public boolean minusUserAmount(String userId,int amount){
		return updateUserAmount(userId, amount, "-");
	}
	
	/**
	 * 账号余额操作
	 * @param userId
	 * @param amount
	 * @param op
	 * @return
	 */
	private boolean updateUserAmount(String userId,int amount,String op){
		synchronized (this) {
			User user = dao.fetch(User.class, Cnd.where("userId", "=", userId));
			int value = user.getAmount();
			Cnd cnd = Cnd.where("userId", "=", userId);
			if("+".equals(op)){
				value += amount;
			}else if("-".equals(op)){
				if(user.getAmount()>=amount){
					value -= amount;
					cnd.and("amount", ">=", amount);
				}else{
					return false;
				}
			}else{
				return false;
			}
			if(dao.update(User.class, Chain.make("amount", value), cnd)>0){
				return true;
			}
			return false;
		}
	}

	@Override
	public NutMap sendPay(String openid, int momney,String mch_id,String wxappid,String apiKey) throws Exception {
		System.out.println(apiKey);
		log.info("method=sendPay|openId:"+openid+",momney:"+momney+",mch_id:"+mch_id+"wxappid"+wxappid+",apiKey"+apiKey);
		NutMap m = ClientSendHongBaoCustomSSL.sxtd(openid,momney, mch_id, wxappid,apiKey);
//		NutMap m = ClientSendHongBaoCustomSSL.sxtd1(openid,momney, mch_id, wxappid,apiKey);
		return m;
	}

	@Override
	public int countwithdrawalTimes(String userId) {
		Calendar cal=Calendar.getInstance();
		cal.add(Calendar.DATE,-1);
		Date time=cal.getTime();
		int i =dao.count(WithdrawalLog.class,Cnd.where("openId", "=", userId).and("crateTime",">",time));
		return i;
	
	}

	@Override
	public Object isConcern(String weixinOpenId) {
		NutMap m = NutMap.NEW();
		String subscribe = "";
		String access_token = "";
		Cache cache = cacheManager.getCache("tockCache");
		Element e = cache.get("ACCESS_TOKEN");
		if(null != e && null != e.getValue()){
			access_token=(String) e.getValue();
			System.out.println("缓存中获取"+access_token);
		}
		if(Strings.isNotBlank(access_token)){
			Response response = Http.get(userInfoUrl.replaceFirst("P_ACCESS_TOKEN", access_token).replaceFirst("P_OPENID", weixinOpenId), Header.create().set("Accept-Charset", "GBK"), 60000);
			if(response.isOK()){
				if(NutMap.WRAP(response.getContent()).containsKey("subscribe")){
					subscribe = NutMap.WRAP(response.getContent()).getString("subscribe");
				     if(subscribe.equals("0")){
				    	 m.addv("code",0).addv("msg", "请先关注公众号!");
				     }
				     if(subscribe.equals("1")){
				    	 m.addv("code",1).addv("msg", "已关注公众号!");
				     }
				     return m;
				}
			}
		}
		Response response = Http.get(tokenUrl.replaceFirst("P_APPID", appId).replaceFirst("P_SECRET", weixinSecret));
		if(response.isOK()){
			access_token = NutMap.WRAP(response.getContent()).getString("access_token");
			cache.put(new Element("ACCESS_TOKEN",access_token));
			System.out.println("新获取的"+cache.get("ACCESS_TOKEN").getValue());
			response = Http.get(userInfoUrl.replaceFirst("P_ACCESS_TOKEN", access_token).replaceFirst("P_OPENID", weixinOpenId), Header.create().set("Accept-Charset", "GBK"), 60000);
			if(response.isOK()){
				if(NutMap.WRAP(response.getContent()).containsKey("subscribe")){
					subscribe = NutMap.WRAP(response.getContent()).getString("subscribe");
				     if(subscribe.equals("0")){
				    	 m.addv("code",0).addv("msg", "请先关注公众号!");
				     }
				     if(subscribe.equals("1")){
				    	 m.addv("code",1).addv("msg", "已关注公众号!");
				     }
				     return m;
				}
			}
		}
		return m.addv("code",2).addv("msg", "未登录");
	}

	@Override
	public List<WithdrawalLog> getWithdrawalLogs(String id, String openId) {
		Cnd cnd = null;
		if(Strings.isNotBlank(id) && Strings.isNotBlank(openId)){
			 cnd = Cnd.where("id", "=", id).and("openId", "=", openId);
		}
		if(Strings.isNotBlank(id) && Strings.isBlank(openId)){
			 cnd = Cnd.where("id", "=", id);
		}
		if(Strings.isBlank(id) && Strings.isNotBlank(openId)){
			cnd = Cnd.where("openId", "=", openId);
		}
		List<WithdrawalLog> list = (List<WithdrawalLog>) dao.query(WithdrawalLog.class,cnd);
		return list;
	}
}
